#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from exceptions import SaverHandleError
from settings import Settings
from influxdb import InfluxDBClient
import csv
import os
import sys


class Saver:
    def __init__(self, identifier):
        """
        :param identifier: 客户端标识符，user和datetime组成的二元组
        """
        self.user = identifier[0]
        self.dt = identifier[1]
        self.identifier = "{}_{}".format(self.user, self.dt)

    def __del__(self):
        """
        析构函数，用于销毁saver对象，关闭数据库连接等
        :return:
        """
        raise SaverHandleError("Undefined __del__ method")

    @staticmethod
    def _cleansing_header(header):
        """将 {groupname:xxx, username:xxx, datetime:xxx}
         的字典洗成列表"""
        return ['ClientName', 'Index', 'TimeStamp'] + header["groupname"]

    def _cleansing_stats(self, stats):
        """黄 [{targetframe:xxx, groupdata:xxx, timestamp:xxx} ...]
         的嵌套字典列表洗成嵌套列表"""
        stats_list = [[self.user, self.dt, stat["timestamp"]] + stat["groupdata"] for stat in stats]
        return stats_list

    def save_header(self, header):
        """写入header列表"""
        raise SaverHandleError("Undefined saver header method")

    def save_stats(self, stats):
        """写入stats嵌套列表"""
        raise SaverHandleError("Undefined saver stats method")


class ConsoleSaver(Saver):
    def __del__(self):
        pass

    def save_header(self, header):
        _header = self._cleansing_header(header)
        print(','.join(_header))

    def save_stats(self, stats):
        _stats = self._cleansing_stats(stats)
        for stat in _stats:
            stat = map(lambda x: str(x), stat)
            print(','.join(stat))


class CSVSaver(Saver):
    def __init__(self, identifier):
        super(CSVSaver, self).__init__(identifier)
        file = "{}_{}.csv".format(self.user, self.dt)
        self.file = os.path.join(Settings.CSV_DIR, file)

    def __del__(self):
        pass

    def save_header(self, header):
        _header = self._cleansing_header(header)
        with open(self.file, "w", encoding='utf-8') as f:
            f_csv = csv.writer(f)
            f_csv.writerow(_header)

    def save_stats(self, stats):
        _stats = self._cleansing_stats(stats)
        with open(self.file, "a", encoding='utf-8') as f:
            f_csv = csv.writer(f)
            f_csv.writerows(_stats)


class InfluxSaver(Saver):
    def __init__(self, identifier):
        super(InfluxSaver, self).__init__(identifier)
        self.inf = InfluxDBClient(
            host=Settings.INFLUXDB_HOST,
            port=Settings.INFLUXDB_PORT,
            username=Settings.INFLUXDB_USER,
            password=Settings.INFLUXDB_PASS,
            database=Settings.INFLUXDB_DATABASE,
        )
        self.header = []

    def __del__(self):
        self.inf.close()

    def save_header(self, header):
        _header = self._cleansing_header(header)
        self.header = _header

    def save_stats(self, stats):
        _stats = self._cleansing_stats(stats)
        for stat in _stats:
            stat_dict = dict(zip(self.header, stat))
            timestamp = stat_dict['TimeStamp']
            insert_data = [
                {
                    "measurement": Settings.INFLUXDB_MEASUREMENT,
                    "time": timestamp,
                    "fields": stat_dict,
                }
            ]
            self.inf.write_points(insert_data)


def get_saver_list():
    """根据字符串获取Saver"""
    saver_list = Settings.SAVER_LIST
    new_list = []
    module = sys.modules[__name__]
    for saver_name in saver_list:
        saver = getattr(module, saver_name, None)
        if saver:
            new_list.append(saver)
    return new_list
